//给你一个含重复值的二叉搜索树（BST）的根节点 root ，找出并返回 BST 中的所有 众数（即，出现频率最高的元素）。 
//
// 如果树中有不止一个众数，可以按 任意顺序 返回。 
//
// 假定 BST 满足如下定义： 
//
// 
// 结点左子树中所含节点的值 小于等于 当前节点的值 
// 结点右子树中所含节点的值 大于等于 当前节点的值 
// 左子树和右子树都是二叉搜索树 
// 
//
// 
//
// 示例 1： 
// 
// 
//输入：root = [1,null,2,2]
//输出：[2]
// 
//
// 示例 2： 
//
// 
//输入：root = [0]
//输出：[0]
// 
//
// 
//
// 提示： 
//
// 
// 树中节点的数目在范围 [1, 10⁴] 内 
// -10⁵ <= Node.val <= 10⁵ 
// 
//
// 
//
// 进阶：你可以不使用额外的空间吗？（假设由递归产生的隐式调用栈的开销不被计算在内） 
//
// Related Topics 树 深度优先搜索 二叉搜索树 二叉树 👍 780 👎 0

package leetcode.editor.cn;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//java:二叉搜索树中的众数
public class Q0501FindModeInBinarySearchTree {
    public static void main(String[] args){
        Solution solution = new Q0501FindModeInBinarySearchTree().new Solution();
        TreeNode root = new TreeNode(1);
        root.left = null;
        root.right = new TreeNode(2);
        root.right.left = new TreeNode(2);
        solution.findMode(root);
    }
    //leetcode submit region begin(Prohibit modification and deletion)
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

    /**
     * 方法一，没有利用二叉搜索树性质，遍历存map
     */
//    class Solution {
//    public Map<Integer, Integer> countMap = new HashMap<>();
//    public int[] findMode(TreeNode root) {
//        List<Integer> resList = new ArrayList<>();
//        dfs(root);
//        if (countMap.isEmpty()) {
//            return new int[0];
//        }
//        int maxCount = 0;
//        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
//            if (entry.getValue() > maxCount) {
//                maxCount = entry.getValue();
//            }
//        }
//        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
//            if (entry.getValue() == maxCount) {
//                resList.add(entry.getKey());
//            }
//        }
//        int[] res = resList.stream().mapToInt(x -> x).toArray();
//        return res;
//    }
//
//    public void dfs(TreeNode root) {
//        if (root == null) {
//            return;
//        }
//        countMap.put(root.val, countMap.getOrDefault(root.val, 0) + 1);
//        dfs(root.left);
//        dfs(root.right);
//    }
//}

/**
 * 方法二，利用二叉搜索树，中序遍历为有序数组
 */
class Solution {
    // 记录上一层递归的入参，用于记录二叉树的父节点
    TreeNode pre;
    List<Integer> resList = new ArrayList<>();
    int maxCount = 0;
    int count = 0;
    public int[] findMode(TreeNode root) {
        if (root == null) {
            return null;
        }
        if (root.left == null && root.right == null) {
            return new int[]{root.val};
        }
        dfs(root);
        return resList.stream().mapToInt(x -> x).toArray();
    }
    public void dfs(TreeNode cur) {
        if (cur == null) {
            return;
        }
        dfs(cur.left);

        if (pre == null) { // 第一个节点
            count = 1;
        } else if (cur.val == pre.val) { // 相等
            count++;
        } else { // 不相等
            count = 1;
        }

        if (maxCount == count) {
            resList.add(cur.val);
        }

        if (maxCount < count) {
            maxCount = count;
            // 清空
            resList.clear();
            resList.add(cur.val);
        }
        // 记录父节点
        pre = cur;
        dfs(cur.right);
        return;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}